package br.ufmg.dees.insane.parser;

import java.util.ArrayList;
import java.util.ListIterator;

import br.ufmg.dees.insane.materialMedia.degeneration.Degeneration;
import br.ufmg.dees.insane.model.femModel.FemModel;
import br.ufmg.dees.insane.model.femModel.element.Element;
import br.ufmg.dees.insane.model.postp.Boundary;
import br.ufmg.dees.insane.model.postp.GeoPostpModel;
import br.ufmg.dees.insane.model.postp.Patch;
import br.ufmg.dees.insane.model.postp.PointModel;
import br.ufmg.dees.insane.util.IPoint3d;
import br.ufmg.dees.insane.util.IVector;

/**
 * This class fill a PostpModel from a FemModel.
 * @author Samuel Silva Penna
 * @since 16/06/2006
 */
public class GaussFemlToGeoPostpModel implements ParserPostpModel {

	//observer of the FemModel...
	// is observed by parserHalfEdge...
	
	private FemModel fem;
	private GeoPostpModel geoPostpModel;
	
	/** The constructor
	 * Constructs a PostpModel from a FemModel.
	 * @param fem The fem model to be passed as parameter
	 */
	public GaussFemlToGeoPostpModel(FemModel fem){
		this.fem = fem;
		this.fillPostpModel();
	}
	
	public void fillPostpModel(){
		ArrayList elements = new ArrayList();
		ArrayList<PointModel> gaussPoints = new ArrayList<PointModel>();
		ArrayList<Patch> patches = new ArrayList<Patch>();
		ArrayList<Boundary> boundaries  = new ArrayList<Boundary>();
		Patch patch;
		PointModel gaussPointModel;
		String[] patchLabels;
		
		elements = this.fem.getElementsList();
		
		//Creating the gauss points Model
        Element element;
        Degeneration dg;
        double[] ipCoords;
         
        
        if(((Degeneration)((Element)elements.get(0)).getDegenerations().get(0)).getRepresentation()!=null){
            for(int i=0;i<elements.size();i++){
                element = (Element)elements.get(i);
                patchLabels = new String[element.getDegenerations().size()];
                for(int j=0;j<element.getDegenerations().size();j++){
                    dg = (Degeneration)element.getDegenerations().get(j);
                     ipCoords = ((Element)element).getCartesianPointCoords(
                                  dg.getRepresentation().getNaturalcoords().toDouble()).toDoubleArray();
                    
                     if(ipCoords.length==2){
                         gaussPointModel = new PointModel(new IPoint3d(ipCoords[0],ipCoords[1],0));
                     }else {
                         gaussPointModel = new PointModel(new IPoint3d(ipCoords[0],ipCoords[1],ipCoords[2]));
                     }
                     gaussPointModel.setLabel("E"+element.getLabel()+"-IP-"+(j+1));
                     //Setting values of  GeneralizedStrains
                     IVector intvarGS = ((Element)element).getPointInternalVariables(dg);
                     IVector intvarGT = ((Element)element).getPointInternalVariables(dg);
                     for (int k=0;k<element.getAnalysisModel().getNumberOfInternalVariables(); k++){
                        gaussPointModel.putValue(element.getAnalysisModel().getInternalVariablesLabels()[k]
                                                ,new Double(intvarGS.getElement(k)));
                        
                        gaussPointModel.putValue(element.getAnalysisModel().getDualInternalVariablesLabels()[k]
                                                 ,new Double(((IVector)dg.mountDualInternalVariableVector(intvarGT)).getElement(k)));
                     }
                     
                     if(!this.checkPointModel(gaussPointModel,gaussPoints)){
                         gaussPoints.add(gaussPointModel);
                         patchLabels[j] = gaussPointModel.getLabel();
                     }else{
                         patchLabels[j] = gaussPointModel.getLabel();
                     }
                }
                
                 patch = new Patch(patchLabels);
                 patch.setLabel(((Element)elements.get(i)).getLabel());
                 patches.add(patch);
                 this.geoPostpModel = new GeoPostpModel(gaussPoints,patches,boundaries);
                 this.geoPostpModel.setLabel("IPGeoPostp");
            }
        }
 }//end of this method
	
	/**The method check if a node exist in a list.
	 * @param vertice 
	 * @param verticesList
	 * @return compare
	 */
	public boolean checkPointModel(PointModel point, ArrayList pointList){
		boolean compare = false;
		ListIterator itr = pointList.listIterator();	
		while(itr.hasNext()){
			PointModel p = (PointModel)itr.next();
			if(p.getLabel().equals(point.getLabel())){
				return true;
			}else{
				 continue;
			}
		}
	return compare;
	}
	
	/** O m�todo busca, na lista do modelo, um v�rtice igual ao vertice passado de parametro, e o retorna
	 * @param vertex
	 * @param verticesList
	 * @return
	 */
	public PointModel searchPointModel(PointModel point, ArrayList pointList){
		PointModel p = new PointModel();
		ListIterator itr = pointList.listIterator();	
		while(itr.hasNext()){
			p = (PointModel)itr.next();
			if(p.getLabel().equals(point.getLabel())){
				return  p;
			 }else{
				 continue;
			 }
		}
	return null;
	}
	
	/**
	 * The method return the femModel.
	 * @return Returns The fem.
	 */
	public FemModel getFem() {
		return fem;
	}

	/**
	 * The method set the field fem from the parameter fem.
	 * @param fem The fem to set.
	 */
	public void setFem(FemModel fem) {
		this.fem = fem;
	}

    public GeoPostpModel getGeoPostpModel() {
        return this.geoPostpModel;
    }

	public void setGeoPostpModel(GeoPostpModel geoPostpModel) {
		this.geoPostpModel = geoPostpModel;
	}
    
//***************************************************************************
}//end of this class

